Hallitse Scikit-learn Pipelines -toimintoa tehostaaksesi koneoppimisen työnkulkuja. Opi automatisoimaan esikäsittely, mallien koulutus ja hyperparametrien viritys luotettavien, toistettavien ja tuotantovalmiiden mallien saavuttamiseksi.
Scikit-learn Pipeline: Paras opas ML-työnkulun automatisointiin
Koneoppimisen maailmassa mallin rakentaminen kuvataan usein loistavana viimeisenä askeleena. Kokeneet datatieteilijät ja ML-insinöörit tietävät kuitenkin, että matka vankkaan malliin on kivetty useilla ratkaisevilla, usein toistuvilla ja virheille alttiilla vaiheilla: tiedon puhdistus, ominaisuuksien skaalaus, kategoristen muuttujien koodaus ja paljon muuta. Näiden vaiheiden hallinta erikseen koulutus-, validointi- ja testausjoukoille voi nopeasti muuttua logistiseksi painajaiseksi, mikä johtaa hienovaraisiin virheisiin ja, mikä on vaarallisinta, tietovuotoon.
Tässä kohtaa Scikit-learnin Pipeline tulee apuun. Se ei ole pelkästään mukavuutta, vaan perustyökalu ammattimaisten, toistettavien ja tuotantovalmiiden koneoppimisjärjestelmien rakentamiseen. Tämä kattava opas opastaa sinut läpi kaiken, mitä sinun tarvitsee tietää Scikit-learn Pipelines -toiminnon hallitsemisesta, peruskäsitteistä edistyneisiin tekniikoihin.
Ongelma: Manuaalinen koneoppimisen työnkulku
Otetaan esimerkiksi tyypillinen ohjattu oppimistehtävä. Ennen kuin voit edes kutsua model.fit(), sinun on valmisteltava tietosi. Vakiotyönkulku voi näyttää tältä:
- Jaa data: Jaa tietojoukko koulutus- ja testausjoukkoihin. Tämä on ensimmäinen ja kriittisin vaihe sen varmistamiseksi, että voit arvioida mallisi suorituskykyä näkemättömillä tiedoilla.
- Käsittele puuttuvat arvot: Tunnista ja imputoi puuttuvat tiedot koulutusjoukossasi (esim. käyttämällä keskiarvoa, mediaania tai vakiota).
- Koodaa kategoriset ominaisuudet: Muunna numeeriset sarakkeet, kuten 'Maa' tai 'Tuoteluokka', numeeriseen muotoon käyttämällä tekniikoita, kuten One-Hot Encoding tai Ordinal Encoding.
- Skaalaa numeeriset ominaisuudet: Tuo kaikki numeeriset ominaisuudet samalle asteikolle käyttämällä menetelmiä, kuten standardointi (
StandardScaler) tai normalisointi (MinMaxScaler). Tämä on ratkaisevan tärkeää monille algoritmeille, kuten SVM:ille, logistiselle regressiolle ja hermoverkoille. - Kouluta malli: Lopuksi sovita valitsemasi koneoppimismalli esikäsitellylle koulutustiedolle.
Kun haluat tehdä ennusteita testijoukossasi (tai uusilla, näkemättömillä tiedoilla), sinun on toistettava täsmälleen samat esikäsittelyvaiheet. Sinun on sovellettava samaa imputointistrategiaa (käyttämällä koulutusjoukosta laskettua arvoa), samaa koodausskeemaa ja samoja skaalausparametreja. Kaikkien näiden sovitettujen muuntajien manuaalinen seuraaminen on tylsää ja suuri virhelähde.
Suurin riski tässä on tietovuoto. Tämä tapahtuu, kun testijoukon tietoja vuotaa vahingossa koulutusprosessiin. Jos esimerkiksi lasket imputoinnin keskiarvon tai skaalausparametrit koko tietojoukosta ennen jakamista, mallisi oppii implisiittisesti testitiedoista. Tämä johtaa liian optimistiseen suorituskykyarvioon ja malliin, joka epäonnistuu surkeasti todellisessa maailmassa.
Esittelyssä Scikit-learn Pipelines: Automatisoitu ratkaisu
Scikit-learn Pipeline on objekti, joka ketjuttaa yhteen useita tiedonmuunnosvaiheita ja lopullisen estimaattorin (kuten luokittelijan tai regressorin) yhdeksi, yhtenäiseksi objektiksi. Voit ajatella sitä datasi kokoonpanolinjana.
Kun kutsut .fit() Pipeline-objektilla, se soveltaa peräkkäisesti fit_transform() jokaiselle välivaiheelle koulutustiedoissa, välittäen yhden vaiheen tuloksen seuraavan syötteenä. Lopuksi se kutsuu .fit() viimeisellä askeleella, estimaattorilla. Kun kutsut .predict() tai .transform() Pipeline-objektilla, se soveltaa vain jokaisen välivaiheen .transform()-menetelmää uusiin tietoihin ennen ennusteen tekemistä lopullisella estimaattorilla.
Pipelines-toiminnon käytön tärkeimmät edut
- Tietovuodon ehkäisy: Tämä on kriittisin etu. Sisällyttämällä kaikki esikäsittely putkistoon varmistat, että muunnokset opitaan ainoastaan koulutusdatasta ristivalidoinnin aikana ja niitä sovelletaan oikein validointi-/testitietoihin.
- Yksinkertaisuus ja organisointi: Koko työnkulku raa'asta datasta koulutettuun malliin on tiivistetty yhdeksi objektiksi. Tämä tekee koodistasi puhtaamman, luettavampaan ja helpommin hallittavan.
- Toistettavuus: Pipeline-objekti kapseloi koko mallinnusprosessisi. Voit helposti tallentaa tämän yksittäisen objektin (esim. käyttämällä `joblib` tai `pickle`) ja ladata sen myöhemmin ennusteiden tekemistä varten, varmistaen, että täsmälleen samoja vaiheita noudatetaan joka kerta.
- Tehokkuus ristikohdehaussa: Voit suorittaa hyperparametrien virityksen koko putkilinjan läpi kerralla ja löytää parhaat parametrit sekä esikäsittelyvaiheille että lopulliselle mallille samanaikaisesti. Tutkimme tätä tehokasta ominaisuutta myöhemmin.
Ensimmäisen yksinkertaisen putkiston rakentaminen
Aloitetaan perusesimerkillä. Kuvittele, että meillä on numeerinen tietojoukko ja haluamme skaalata tiedot ennen logistisen regression mallin kouluttamista. Tässä on, miten rakennat putkilinjan sitä varten.
Ensinnäkin, asetetaan ympäristömme ja luodaan joitain esimerkkidataa.
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.metrics import accuracy_score
# Luo joitain esimerkkidataa
X, y = np.random.rand(100, 5) * 10, (np.random.rand(100) > 0.5).astype(int)
# Jaa data koulutus- ja testijoukkoihin
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
Määritellään nyt putkilinjamme. Putkilinja luodaan antamalla luettelo vaiheista. Jokainen vaihe on tuple, joka sisältää nimen (valintasi merkkijono) ja muunnin- tai estimaattoriobjektin itsessään.
# Luo putkiston vaiheet
steps = [
('scaler', StandardScaler()),
('classifier', LogisticRegression())
]
# Luo Pipeline-objekti
pipe = Pipeline(steps)
# Nyt voit käsitellä 'pipe'-objektia ikään kuin se olisi tavallinen malli.
# Koulutetaan se koulutusdatallamme.
pipe.fit(X_train, y_train)
# Tee ennusteita testidatasta
y_pred = pipe.predict(X_test)
# Arvioi malli
accuracy = accuracy_score(y_test, y_pred)
print(f"Putkiston tarkkuus: {accuracy:.4f}")
Siinä se! Vain muutamalla rivillä olemme yhdistäneet skaalauksen ja luokittelun. Scikit-learn hoitaa kaiken väliloogikan. Kun pipe.fit(X_train, y_train) kutsutaan, se ensin kutsuu StandardScaler().fit_transform(X_train) ja välittää sitten tuloksen LogisticRegression().fit(). Kun pipe.predict(X_test) kutsutaan, se soveltaa jo sovitettua skaalausohjelmaa käyttämällä StandardScaler().transform(X_test) ennen ennusteiden tekemistä logistisen regression mallilla.
Heterogeenisten tietojen käsittely: `ColumnTransformer`
Todelliset tietojoukot ovat harvoin yksinkertaisia. Ne sisältävät usein eri tyyppisiä tietoja: numeerisia sarakkeita, jotka on skaalattava, kategorisia sarakkeita, jotka on koodattava, ja ehkä tekstisarakkeita, jotka on vektorisoitava. Yksinkertainen peräkkäinen putkilinja ei riitä tähän, koska sinun on sovellettava eri muunnoksia eri sarakkeisiin.
Tässä kohtaa ColumnTransformer loistaa. Sen avulla voit soveltaa eri muuntajia eri datasarakkeiden osajoukkoihin ja yhdistää sitten tulokset älykkäästi. Se on täydellinen työkalu käytettäväksi esikäsittelyvaiheena suuremmassa putkilinjassa.
Esimerkki: Numeeristen ja kategoristen ominaisuuksien yhdistäminen
Luodaan realistisempi tietojoukko, jossa on sekä numeerisia että kategorisia ominaisuuksia käyttämällä pandasia.
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder
from sklearn.impute import SimpleImputer
# Luo esimerkkikehys
data = {
'age': [25, 30, 45, 35, 50, np.nan, 22],
'salary': [50000, 60000, 120000, 80000, 150000, 75000, 45000],
'country': ['USA', 'Canada', 'USA', 'UK', 'Canada', 'USA', 'UK'],
'purchased': [0, 1, 1, 0, 1, 1, 0]
}
df = pd.DataFrame(data)
X = df.drop('purchased', axis=1)
y = df['purchased']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Tunnista numeeriset ja kategoriset sarakkeet
numerical_features = ['age', 'salary']
categorical_features = ['country']
Esikäsittelystrategiamme on:
- Numeerisille sarakkeille (
age,salary): Imputoi puuttuvat arvot mediaanilla, ja skaalaa ne sitten. - Kategorisille sarakkeille (
country): Imputoi puuttuvat arvot yleisimmällä luokalla ja tee niistä sitten one-hot-koodaus.
Voimme määrittää nämä vaiheet käyttämällä kahta erillistä miniputkilinjaa.
# Luo putkilinja numeerisille ominaisuuksille
numeric_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler())
])
# Luo putkilinja kategorisille ominaisuuksille
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='most_frequent')),
('onehot', OneHotEncoder(handle_unknown='ignore'))
])
Käytämme nyt ColumnTransformer-toimintoa näiden putkilinjojen soveltamiseen oikeisiin sarakkeisiin.
# Luo esikäsittelijä ColumnTransformer-toiminnolla
preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numerical_features),
('cat', categorical_transformer, categorical_features)
])
ColumnTransformer ottaa luettelon transformers-toiminnosta. Jokainen muunnin on tuple, joka sisältää nimen, muunninobjektin (joka voi olla itse putkilinja) ja sarakkeiden nimiluettelon, joihin sitä sovelletaan.
Lopuksi voimme sijoittaa tämän preprocessor-toiminnon pääputkilinjamme ensimmäiseksi vaiheeksi, jota seuraa lopullinen estimaattorimme.
from sklearn.ensemble import RandomForestClassifier
# Luo täysi putkilinja
full_pipeline = Pipeline(steps=[
('preprocessor', preprocessor),
('classifier', RandomForestClassifier(random_state=42))
])
# Kouluta ja arvioi täysi putkilinja
full_pipeline.fit(X_train, y_train)
print("Mallin pistemäärä testidatalla:", full_pipeline.score(X_test, y_test))
# Nyt voit tehdä ennusteita uusista raakadatoista
new_data = pd.DataFrame({
'age': [40, 28],
'salary': [90000, 55000],
'country': ['USA', 'Germany'] # 'Germany' on tuntematon luokka
})
predictions = full_pipeline.predict(new_data)
print("Ennusteet uusille tiedoille:", predictions)
Huomaa, kuinka tyylikkäästi tämä käsittelee monimutkaista työnkulkua. Parametri handle_unknown='ignore' OneHotEncoder-toiminnossa on erityisen hyödyllinen tuotantojärjestelmissä, koska se estää virheet, kun tiedoissa esiintyy uusia, näkemättömiä kategorioita.
Edistyneet putkilinjatekniikat
Pipelines tarjoavat vielä enemmän voimaa ja joustavuutta. Tutkitaan joitain edistyneitä ominaisuuksia, jotka ovat välttämättömiä ammattimaisille koneoppimisprojekteille.
Omien muuntajien luominen
Joskus sisäänrakennetut Scikit-learn-muuntajat eivät riitä. Saatat joutua suorittamaan toimialakohtaisen muunnoksen, kuten ominaisuuden logaritmin poistaminen tai kahden ominaisuuden yhdistäminen uudeksi. Voit helposti luoda omat mukautetut muuntajasi, jotka integroivat saumattomasti putkilinjaan.
Tätä varten luot luokan, joka perii luokasta BaseEstimator ja TransformerMixin. Sinun tarvitsee toteuttaa vain fit()- ja transform()-menetelmät (ja __init__(), jos tarpeellista).
Luodaan muunnin, joka lisää uuden ominaisuuden: palkan ja iän suhde.
from sklearn.base import BaseEstimator, TransformerMixin
# Määritä sarakeindeksit (voi myös välittää nimiä)
age_ix, salary_ix = 0, 1
class FeatureRatioAdder(BaseEstimator, TransformerMixin):
def __init__(self):
pass # Ei parametreja asetettavaksi
def fit(self, X, y=None):
return self # Ei opittavaa fitin aikana, joten palauta vain itse
def transform(self, X):
salary_age_ratio = X[:, salary_ix] / X[:, age_ix]
return np.c_[X, salary_age_ratio] # Yhdistä alkuperäinen X ja uusi ominaisuus
Voit sitten lisätä tämän mukautetun muuntajan numeeriseen käsittelyputkilinjaasi:
numeric_transformer_with_custom = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median')),
('ratio_adder', FeatureRatioAdder()), # Oma mukautettu muunnin
('scaler', StandardScaler())
])
Tämä räätälöintiaste mahdollistaa kaiken ominaisuusteknisen logiikkasi kapseloimisen putkilinjaan, mikä tekee työnkulustasi erittäin kannettavan ja toistettavan.
Hyperparametrien viritys putkilinjojen avulla käyttämällä `GridSearchCV`
Tämä on luultavasti yksi Pipelines-toiminnon tehokkaimmista sovelluksista. Voit etsiä parhaita hyperparametreja koko työnkulullesi, mukaan lukien esikäsittelyvaiheet ja lopullinen malli, kaikki kerralla.
Määrittääksesi, mitä parametreja viritetään, käytät erityistä syntaksia: step_name__parameter_name.
Laajennetaan edellistä esimerkkiämme ja viritetään sekä esikäsittelijämme imputerin että `RandomForestClassifier` -toiminnon hyperparametrit.
from sklearn.model_selection import GridSearchCV
# Käytämme 'full_pipeline' ColumnTransformer -esimerkistä
# Määritä parametriritilä
param_grid = {
'preprocessor__num__imputer__strategy': ['mean', 'median'],
'classifier__n_estimators': [50, 100, 200],
'classifier__max_depth': [None, 10, 20],
'classifier__min_samples_leaf': [1, 2, 4]
}
# Luo GridSearchCV-objekti
grid_search = GridSearchCV(full_pipeline, param_grid, cv=5, verbose=1, n_jobs=-1)
# Sovita se dataan
grid_search.fit(X_train, y_train)
# Tulosta parhaat parametrit ja pistemäärä
print("Löydetyt parhaat parametrit: ", grid_search.best_params_)
print("Paras ristiinvalidoinnin pistemäärä: ", grid_search.best_score_)
# Paras estimaattori on jo sovitettu uudelleen koko koulutusdataan
best_model = grid_search.best_estimator_
print("Testijoukon pistemäärä parhaalla mallilla: ", best_model.score(X_test, y_test))
Tarkastele tarkasti avaimia param_grid-toiminnossa:
'preprocessor__num__imputer__strategy': Tämä kohdistuu `strategy`-parametriinSimpleImputer-vaiheessa nimeltä `imputer` numeerisessa putkilinjassa nimeltä `num`, joka itse on `ColumnTransformer` -toiminnossa nimeltä `preprocessor`.'classifier__n_estimators': Tämä kohdistuu viimeisen estimaattorin nimeltä `classifier` parametriin `n_estimators`.
Tekemällä tämän GridSearchCV yrittää oikein kaikkia yhdistelmiä ja löytää optimaalisen parametrijoukon koko työnkululle, estäen täysin tietovuodon viritysprosessin aikana, koska kaikki esikäsittely tehdään jokaisen ristiinvalidoinnin sisällä.
Putkilinjasi visualisointi ja tarkastelu
Monimutkaiset putkilinjat voivat olla vaikeita ajatella. Scikit-learn tarjoaa hienon tavan visualisoida niitä. Versiosta 0.23 alkaen voit saada interaktiivisen HTML-esityksen.
from sklearn import set_config
# Määritä näyttö arvoon 'diagram' saadaksesi visuaalisen esityksen
set_config(display='diagram')
# Nyt putkilinjan objektin näyttäminen Jupyter Notebookissa tai vastaavassa ympäristössä renderöi sen
full_pipeline
Tämä luo kaavion, joka näyttää datan kulun jokaisen muuntajan ja estimaattorin läpi sekä niiden nimet. Tämä on uskomattoman hyödyllistä virheenkorjaukseen, työn jakamiseen ja mallisi rakenteen ymmärtämiseen.
Voit myös käyttää sovitettujen putkilinjojen yksittäisiä vaiheita niiden nimien avulla:
# Käytä sovitun putkilinjan lopullista luokittelijaa
final_classifier = full_pipeline.named_steps['classifier']
print("Ominaisuuksien tärkeysjärjestys:", final_classifier.feature_importances_)
# Käytä OneHotEncoderia nähdäksesi opitut kategoriat
onehot_encoder = full_pipeline.named_steps['preprocessor'].named_transformers_['cat'].named_steps['onehot']
print("Opiit kategoriset ominaisuudet:", onehot_encoder.categories_)
Yleiset sudenkuopat ja parhaat käytännöt
- Sovitetaan väärään dataan: Sovita aina putkilinjasi VAIN koulutusdataan. Älä koskaan sovi sitä koko tietojoukkoon tai testijoukkoon. Tämä on pääsääntö tietovuodon estämiseksi.
- Tietomuodot: Muista kunkin vaiheen odottama tietomuoto. Jotkut muuntajat (kuten mukautetussa esimerkissämme) saattavat toimia NumPy-taulukoilla, kun taas toiset ovat helpompia Pandas DataFrame -toiminnolla. Scikit-learn on yleensä hyvä tämän käsittelyssä, mutta se on huomioitava, erityisesti mukautetuilla muuntajilla.
- Putkilinjojen tallentaminen ja lataaminen: Mallin käyttöönottoa varten sinun on tallennettava sovitettu putkilinja. Tavanomainen tapa tehdä tämä Python-ekosysteemissä on `joblib` tai `pickle`. `joblib` on usein tehokkaampi objekteille, jotka sisältävät suuria NumPy-taulukoita.
import joblib # Tallenna putkilinja joblib.dump(full_pipeline, 'my_model_pipeline.joblib') # Lataa putkilinja myöhemmin lated_pipeline = joblib.load('my_model_pipeline.joblib') # Tee ennusteita ladatulla mallilla lated_pipeline.predict(new_data) - Käytä kuvaavia nimiä: Anna putkilinjan vaiheille ja
ColumnTransformer-komponenteille selkeät, kuvaavat nimet (esim. 'numeric_imputer', 'categorical_encoder', 'svm_classifier'). Tämä tekee koodistasi luettavampaa ja yksinkertaistaa hyperparametrien viritystä ja virheenkorjausta.
Johtopäätös: Miksi Pipelines ovat välttämättömiä ammattimaiselle ML:lle
Scikit-learn Pipelines ei ole vain työkalu siistimmän koodin kirjoittamiseen; ne edustavat paradigman muutosta manuaalisesta, virheille alttiista skriptauksesta systemaattiseen, vankkaan ja toistettavaan lähestymistapaan koneoppimiseen. Ne ovat hyvien ML-tekniikoiden selkäranka.
Ottamalla käyttöön putkilinjoja, saat:
- Vahvuus: Poistat yleisimmän virhelähteen koneoppimisprojekteissa - tietovuodon.
- Tehokkuus: Virtaviivaistat koko työnkulun, ominaisuusteknisestä hyperparametrien viritykseen, yhdeksi yhtenäiseksi yksiköksi.
- Toistettavuus: Luo yhden, sarjoitettavan objektin, joka sisältää koko mallilogiikkasi, mikä helpottaa käyttöönottoa ja jakamista.
Jos suhtaudut vakavasti sellaisten koneoppimismallien rakentamiseen, jotka toimivat luotettavasti todellisessa maailmassa, Scikit-learn Pipelines-toiminnon hallinta ei ole valinnainen - se on välttämätöntä. Aloita niiden sisällyttäminen projekteihisi jo tänään, ja rakennat parempia, luotettavampia malleja nopeammin kuin koskaan ennen.